package com.zy.reflect.privateaccess;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @Author Gong
 * @Description
 * @dATE 2021/12/20 9:36
 **/
public class Test {
    public static void main(String[] args) throws Exception {
        Test t = new Test();
        t.testCon();
    }
    public void testField() throws Exception {
        Class clazz = Person.class;
//获取属性  1.getField(String fieldName)获取运行时类中声明为public的指定属性名为fieldName的属性
        Field fieldName= clazz.getField("name");
//创建运行时类的对象
        Person perso=(Person) clazz.newInstance();
        perso.show();
//将运行时类的指定的属性赋值
        fieldName.set(perso, "jerry");
        perso.show();
//获取属性  1.getDeclaredField(String fieldName)获取运行时类中声明为private的指定属性名为fieldName的属性
        Field fieldAge=clazz.getDeclaredField("age");
//由于属性访问修饰符的限制，要给设置如下属性，才能操作该属性
        fieldAge.setAccessible(true);//设置为可访问的
        fieldAge.set(perso, 22);
        perso.show();
    }

    public void testCon() throws Exception {
        Class clazz = Person.class;
        Constructor cons=clazz.getDeclaredConstructor(String.class,Integer.class);
        cons.setAccessible(true);
        Person p=(Person) cons.newInstance("张少峰",26);
        p.show();
    }

    public void invokeTest() throws Exception {
        Class clazz = Person.class;
//构造一个运行时类的对象
        Person person=(Person) clazz.newInstance();
//getMethod(String methodName,Class...params) //获取运行时类中的public修饰的方法
        Method methodShow=clazz.getMethod("show");
//调用指定的运行时类的方法Object obj=invoke(object obj,Object...args) 该方法是由返回值的
        Object returnVal=methodShow.invoke(person);
        System.out.println(returnVal);
        Method methodToString=clazz.getMethod("toString");
        returnVal=methodToString.invoke(person);
        System.out.println(returnVal);
//调用运行时类中的静态的方法
        Method methodInfo=clazz.getMethod("info");
        methodInfo.invoke(Person.class);
//调用运行时中声明为private的方法
        Method method=clazz.getDeclaredMethod("say",String.class,Integer.class);
//和属性一样，要设置改方法是可访问的
        method.setAccessible(true);
        Object obj=method.invoke(person, "小溪小溪，我是河流",100000);
        System.out.println(obj);
    }

    public void conPerson() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.根据全类名获取对应的Class对象
        String name = "com.zy.reflect.privateaccess.Person";

        Class clazz = null;
        clazz = Class.forName(name);
        //2.调用指定参数结构的构造器，生成Constructor的实例
        Constructor con = clazz.getConstructor(String.class,Integer.class);
        //3.通过Constructor的实例创建对应类的对象，并初始化类属性
        Person p2 = (Person) 	con.newInstance("Peter",20);
        System.out.println(p2);

    }
    public  void getLoader() throws ClassNotFoundException, IOException {
        //1.获取一个系统类加载器
        ClassLoader classloader = ClassLoader.getSystemClassLoader();
        System.out.println(classloader);
//2.获取系统类加载器的父类加载器，即扩展类加载器
        classloader = classloader.getParent();
        System.out.println(classloader);
//3.获取扩展类加载器的父类加载器，即引导类加载器
        classloader = classloader.getParent();
        System.out.println(classloader);
//4.测试当前类由哪个类加载器进行加载
        classloader =
                Class.forName("com.zy.reflect.privateaccess.Person").getClassLoader();
        System.out.println(classloader);

        //5.测试JDK提供的Object类由哪个类加载器加载
        classloader =
                Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classloader);
        //*6.关于类加载器的一个主要方法：getResourceAsStream(String str):获取类路径下的指定文件的输入流
        InputStream in = null;
        in = this.getClass().getClassLoader().getResourceAsStream("mapper\\jdbc.properties");
        System.out.println(in);
        Properties p = new Properties();
        p.load(in);
        String name = p.getProperty("user");
        System.out.println(name);


    }
    public void test0() throws IOException {
//        如果属性文件是在当前工程根目录中的话：
        FileInputStream fis=new FileInputStream(new File("abc.properties"));
        Properties pro=new Properties();
        pro.load(fis);
        String user=pro.getProperty("user");
        String password=pro.getProperty("password");
        System.out.println("user = "+user);
        System.out.println("password = "+password);

    }
    public void test1() throws IOException {
//        配置文件在某个包中
        ClassLoader load=this.getClass().getClassLoader();
        InputStream is=load.getResourceAsStream("mapper/jdbc.properties");
        Properties pro=new Properties();
        pro.load(is);
        String user=pro.getProperty("user");
        String password=pro.getProperty("password");
        System.out.println("user = "+user);
        System.out.println("password = "+password);

    }
    public void test4() throws Exception{
        //1.获取一个系统类加载器
        ClassLoader load1=ClassLoader.getSystemClassLoader();
        System.out.println(load1);
        //2.获取系统类加载器的父类加载器，即扩展类加载器
        ClassLoader load2=load1.getParent();
        System.out.println(load2);
        //观察Class是由那个加载器加载的
        //自定义类是由系统的加载器加载 ：sun.misc.Launcher$AppClassLoader@3e55a58f
        Class clazz1=Person.class;
        ClassLoader pLoad=clazz1.getClassLoader();
        System.out.println(pLoad);
//这个属于核心类，核心类都加载不到
        String className="java.lang.Object";
        Class clazz2=Class.forName(className);
        ClassLoader oLoad=clazz2.getClassLoader();
        System.out.println(oLoad);
    }

    public void test2() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //1.调用运行时类本身的.class属性
        Class clazz1=Person.class;
        System.out.println(clazz1.getName());
        Class clazz2=String.class;
        System.out.println(clazz2.getName());
        //2.通过运行时类的对象来获取
        Person person=new Person();
        Class clazz3=person.getClass();
        System.out.println(clazz3.getName());
        //
        Class clazz = "com.zy.reflect.privateaccess.Person".getClass();
        //3.通过Class的静态方法forName()
        Class clazz4=Class.forName("com.zy.reflect.privateaccess.Person");
        Person p=(Person) clazz4.newInstance();
        System.out.println(clazz4);
        //4.（了解）通过类的加载器来获取Calss的实例
        ClassLoader classLoader=this.getClass().getClassLoader();
        Class clazz5=classLoader.loadClass("com.zy.reflect.privateaccess.Person");



    }
    public void test() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        //        Person p = new Person("zs",19);
//        System.out.println(p.toString());
//        p.show();
//        p.display("中国");

        //2.
        String str = "com.zy.reflect.privateaccess.Person";
        Class clazz = Class.forName(str);
        Object obj = clazz.newInstance();
        Field field = clazz.getField("name");
        field.set(obj, "Peter");
        Object obj2 = field.get(obj);
        System.out.println(obj2);

        //2创建实例
//        Class clazz = Person.class;
//        //创建clazz对应的运行时类的Person类的对象
//        Person p = (Person) clazz.newInstance();
//        Class<? extends Person> aClass = p.getClass();
//
//
//        String s = p.toString();
//        System.out.println(s);
//
//        //获得属性
//        Field f1=clazz.getField("name");
//        f1.set(p, "liudehua");
//        String str = p.toString();
//        System.out.println(str);
//
//        //获得方法
//        Method show = clazz.getMethod("show");
//        show.invoke(p);
//
////        p.display("中国");
//        Method display = clazz.getMethod("display", String.class);
//        display.invoke(p,"中国");
    }
}
